package com.hancheng.goodscloud.business.service.serviceImpl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hancheng.commoncloud.business.entity.dto.IdDTO;
import com.hancheng.commoncloud.business.entity.dto.IdListDTO;
import com.hancheng.commoncloud.framework.contant.Constants;
import com.hancheng.commoncloud.framework.result.PageResult;
import com.hancheng.commoncloud.framework.util.ApiAssert;
import com.hancheng.commoncloud.framework.util.LocalUserInfoUtil;
import com.hancheng.goodscloud.business.entity.dto.GoodsDTO;
import com.hancheng.goodscloud.business.entity.dto.GoodsInsertDTO;
import com.hancheng.goodscloud.business.entity.dto.GoodsUpdateDTO;
import com.hancheng.goodscloud.business.entity.dto.SubtractQuantityDTO;
import com.hancheng.goodscloud.business.entity.po.GoodsPO;
import com.hancheng.goodscloud.business.entity.vo.GoodsVO;
import com.hancheng.goodscloud.business.mapper.GoodsMapper;
import com.hancheng.goodscloud.business.service.GoodsService;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.List;

/**
 * 商品表 ServiceImpl
 *
 * @author 韩诚
 * @date 2025/06/22
 */
@Slf4j
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, GoodsPO> implements GoodsService {

    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private DataSource dataSource;

    @PostConstruct
    public void check() {
        System.out.println("当前数据源类型为：" + dataSource.getClass().getName());
    }


    /**
     * 分页列表
     *
     * @param goodsDTO
     * @return
     */
    @Override
    public PageResult<GoodsVO> getPageList(GoodsDTO goodsDTO) {
        PageHelper.startPage(goodsDTO.getPageNo(), goodsDTO.getPageSize());
        List<GoodsPO> goodsPOList = goodsMapper.selectList(new LambdaQueryWrapper<GoodsPO>().like(StrUtil.isNotBlank(goodsDTO.getGoodsName()), GoodsPO::getGoodsName, goodsDTO.getGoodsName()).like(StrUtil.isNotBlank(goodsDTO.getGoodsCode()), GoodsPO::getGoodsCode, goodsDTO.getGoodsCode()).orderByDesc(GoodsPO::getCreateTime));
        PageInfo<GoodsPO> pageInfo = new PageInfo<>(goodsPOList);
        return new PageResult<>(pageInfo.getTotal(), mapperFacade.mapAsList(goodsPOList, GoodsVO.class));
    }

    /**
     * 下拉框列表
     *
     * @param goodsDTO
     * @return
     */
    public List<GoodsVO> getList(GoodsDTO goodsDTO) {
        List<GoodsPO> goodsPOList = goodsMapper.selectList(new LambdaQueryWrapper<GoodsPO>().like(StrUtil.isNotBlank(goodsDTO.getGoodsName()), GoodsPO::getGoodsName, goodsDTO.getGoodsName()).like(StrUtil.isNotBlank(goodsDTO.getGoodsCode()), GoodsPO::getGoodsCode, goodsDTO.getGoodsCode()).orderByDesc(GoodsPO::getCreateTime));
        return mapperFacade.mapAsList(goodsPOList, GoodsVO.class);
    }

    /**
     * 明细
     *
     * @param idDTO
     * @return
     */
    @Override
    public GoodsVO detail(IdDTO idDTO) {
        GoodsPO goodsPO = goodsMapper.selectById(idDTO.getId());
        return mapperFacade.map(goodsPO, GoodsVO.class);
    }

    /**
     * 新增
     *
     * @param goodsInsertDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = Constants.TIME_OUT)
    @Override
    public void insert(GoodsInsertDTO goodsInsertDTO) {
        //校验名称编码唯一
        checkNameAndCode(null, goodsInsertDTO.getGoodsName(), goodsInsertDTO.getGoodsCode());

        //新增
        GoodsPO goodsPO = mapperFacade.map(goodsInsertDTO, GoodsPO.class);
        goodsPO.setCreateUserId(LocalUserInfoUtil.getAdminUserPO().getUserId());
        goodsMapper.insert(goodsPO);
    }

    /**
     * 修改
     *
     * @param goodsUpdateDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = Constants.TIME_OUT)
    @Override
    public void update(GoodsUpdateDTO goodsUpdateDTO) {
        //校验名称编码唯一
        checkNameAndCode(goodsUpdateDTO.getId(), goodsUpdateDTO.getGoodsName(), goodsUpdateDTO.getGoodsCode());

        //新增
        GoodsPO goodsPO = mapperFacade.map(goodsUpdateDTO, GoodsPO.class);
        goodsPO.setUpdateUserId(LocalUserInfoUtil.getAdminUserPO().getUserId());
        goodsMapper.updateById(goodsPO);
    }

    /**
     * 批量删除
     *
     * @param idListDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = Constants.TIME_OUT)
    @Override
    public void deleteBatch(IdListDTO idListDTO) {
        if (CollUtil.isNotEmpty(idListDTO.getIdList())) {
            goodsMapper.deleteBatchIds(idListDTO.getIdList());
        }
    }

    /**
     * 扣减库存
     *
     * @param subtractQuantityDTO
     */
    @Transactional
    @Override
    public void subtractQuantity(SubtractQuantityDTO subtractQuantityDTO) {
        System.out.println("当前 Seata 全局事务ID (XID): " + RootContext.getXID());

        GoodsPO goodsPO = goodsMapper.selectById(subtractQuantityDTO.getGoodsId());
        ApiAssert.isTrue(goodsPO.getGoodsQuantity() >= subtractQuantityDTO.getQuantity(), "商品库存不够！");
        goodsMapper.update(null, new LambdaUpdateWrapper<GoodsPO>()
                .eq(GoodsPO::getId, subtractQuantityDTO.getGoodsId())
                .setSql("goods_quantity = goods_quantity - " + subtractQuantityDTO.getQuantity()));
    }

    /**
     * 校验名称编码唯一
     *
     * @param id
     * @param goodsName
     * @param goodsCode
     */
    private void checkNameAndCode(Long id, String goodsName, String goodsCode) {
        Integer count = goodsMapper.selectCount(new LambdaQueryWrapper<GoodsPO>()
                .ne(ObjectUtil.isNotNull(id), GoodsPO::getId, id)
                .and(queryWrapper -> queryWrapper
                        .eq(GoodsPO::getGoodsName, goodsName)
                        .or()
                        .eq(GoodsPO::getGoodsCode, goodsCode)
                ));
        ApiAssert.isTrue(count <= Constants.ZERO, "名称或者编码已存在！");
    }
}
